import pino from 'pino';
import { join } from 'path';
import { EnvUtil } from '../common/utils/env.util';

/**
 * Logger 配置接口
 */
export interface ILoggerConfig {
  /** 日志根目录 */
  logDir?: string;
  /** 日志级别 */
  level?: pino.Level;
  /** 是否启用文件日志 */
  fileEnabled?: boolean;
  /** 是否启用控制台日志 */
  consoleEnabled?: boolean;
  /** 单文件最大大小（默认 10M） */
  maxSize?: string;
  /** 滚动频率（daily/hourly，默认 daily） */
  frequency?: 'daily' | 'hourly';
  /** 是否启用独立的 error 日志文件（默认 true） */
  errorFileEnabled?: boolean;
}

/**
 * Logger 工厂类
 * 
 * 提供静态工厂方法获取 Pino Logger 实例，类似 Java Log4j 的 LoggerFactory
 * 支持按业务模块划分日志目录，自动滚动日志文件
 * 
 * 特性：
 * - 静态工厂方法 get(context, module?)
 * - 实例缓存，避免重复创建
 * - 按模块分离日志目录（logs/module/）
 * - 自动按天滚动 + 大小限制
 * - 支持开发/生产环境配置
 * 
 * @example
 * ```ts
 * // 系统级日志（默认 app 模块）
 * const logger = LoggerFactory.get('UserService');
 * logger.info('用户服务启动');
 * 
 * // 业务模块日志（独立目录）
 * const authLogger = LoggerFactory.get('AuthController', 'auth');
 * authLogger.info('用户登录');
 * // 日志文件：logs/auth/auth-2024-01-15.log
 * 
 * // 用户模块日志
 * const userLogger = LoggerFactory.get('UserService', 'user');
 * userLogger.info('创建用户');
 * // 日志文件：logs/user/user-2024-01-15.log
 * ```
 */
export class LoggerFactory {
  // 禁止实例化，仅提供静态方法
  private constructor() {
    throw new Error('LoggerFactory 是静态工具类，无需实例化');
  }

  /** Logger 实例缓存 Map<module, Logger> */
  private static instances = new Map<string, pino.Logger>();

  /** 默认配置 */
  private static defaultConfig: ILoggerConfig = {
    logDir: join(process.cwd(), 'logs'),
    level: EnvUtil.isDev ? 'debug' : 'info',
    fileEnabled: true,
    consoleEnabled: EnvUtil.isDev,
    maxSize: '10M',
    frequency: 'daily',
    errorFileEnabled: true,
  };

  /**
   * 获取 Logger 实例（静态工厂方法）
   *
   * @param context 上下文（类名字符串、类构造函数或对象实例）
   * @param module 业务模块名称（可选，默认为 'app'）
   * @returns Pino Logger 实例
   *
   * @example
   * ```ts
   * // 方式 1：传递字符串
   * const logger = LoggerFactory.get('UserService');
   * logger.info('用户服务启动');
   *
   * // 方式 2：传递类构造函数（推荐）
   * class UserService {}
   * const logger = LoggerFactory.get(UserService);
   * logger.info('用户服务启动');
   *
   * // 方式 3：传递对象实例
   * const logger = LoggerFactory.get(this);
   * logger.info('用户服务启动');
   *
   * // 指定业务模块
   * const authLogger = LoggerFactory.get(AuthController, 'auth');
   * authLogger.info({ userId: 123 }, '用户登录成功');
   * ```
   */
  static get(context: string | Function | object, module: string = 'app'): pino.Logger {
    // 从缓存获取或创建新实例
    if (!this.instances.has(module)) {
      this.instances.set(module, this.createModuleLogger(module));
    }

    const logger = this.instances.get(module)!;

    // 解析上下文名称
    const contextName = this.resolveContextName(context);

    // 返回带上下文的子 Logger
    return logger.child({ context: contextName });
  }

  /**
   * 解析上下文名称
   *
   * @param context 上下文（字符串、类构造函数或对象实例）
   * @returns 上下文名称字符串
   */
  private static resolveContextName(context: string | Function | object): string {
    // 如果是字符串，直接返回
    if (typeof context === 'string') {
      return context;
    }

    // 如果是函数（类构造函数），返回函数名
    if (typeof context === 'function') {
      return context.name || 'Anonymous';
    }

    // 如果是对象实例，返回构造函数名
    if (typeof context === 'object' && context !== null) {
      return context.constructor?.name || 'Object';
    }

    return 'Unknown';
  }

  /**
   * 创建模块级 Logger 实例
   *
   * @param module 模块名称
   * @returns Pino Logger 实例
   */
  private static createModuleLogger(module: string): pino.Logger {
    const config = this.defaultConfig;

    // 构建日志文件路径：logs/module/module-YYYY-MM-DD.log
    const logFile = join(config.logDir!, module, `${module}.log`);
    const errorLogFile = join(config.logDir!, module, `${module}-error.log`);

    // 构建 Pino 基础配置
    const pinoOptions: pino.LoggerOptions = {
      level: config.level,
    };

    // pino-roll 配置选项
    const rollOptions = {
      frequency: config.frequency,
      size: config.maxSize,
      mkdir: true,
      dateFormat: 'yyyy-MM-dd', // 日期格式（使用 date-fns 格式）
    };

    // 构建输出流数组
    const streams: pino.StreamEntry[] = [];

    // 如果启用控制台输出（开发环境）
    if (config.consoleEnabled) {
      streams.push({
        level: config.level,
        stream: pino.transport({
          target: 'pino-pretty',
          options: {
            colorize: true,
            translateTime: 'yyyy-mm-dd HH:MM:ss',
            ignore: 'pid,hostname',
            singleLine: true,
          },
        }),
      });
    }

    // 如果启用文件日志
    if (config.fileEnabled) {
      // 所有日志写入主日志文件
      streams.push({
        level: config.level,
        stream: pino.transport({
          target: 'pino-roll',
          options: {
            file: logFile,
            ...rollOptions,
          },
        }),
      });

      // 如果启用独立 error 日志文件
      if (config.errorFileEnabled) {
        streams.push({
          level: 'error',
          stream: pino.transport({
            target: 'pino-roll',
            options: {
              file: errorLogFile,
              ...rollOptions,
            },
          }),
        });
      }
    }

    // 如果有多个输出流，使用 multistream
    if (streams.length > 1) {
      return pino(pinoOptions, pino.multistream(streams));
    }

    // 如果只有一个输出流，直接使用该流
    if (streams.length === 1) {
      return pino(pinoOptions, streams[0].stream);
    }

    // 如果没有配置任何输出流，使用默认控制台输出
    return pino(pinoOptions);
  }

  /**
   * 设置全局配置
   * 
   * @param config 配置选项
   * 
   * @example
   * ```ts
   * // 在应用启动时配置
   * LoggerFactory.configure({
   *   logDir: '/var/log/myapp',
   *   level: 'info',
   *   maxSize: '50M',
   *   frequency: 'hourly',
   * });
   * ```
   */
  static configure(config: Partial<ILoggerConfig>): void {
    this.defaultConfig = { ...this.defaultConfig, ...config };
    // 清空缓存，强制重新创建实例
    this.instances.clear();
  }

  /**
   * 清空所有缓存的 Logger 实例
   * 
   * 用于测试或需要重新初始化的场景
   */
  static clearCache(): void {
    this.instances.clear();
  }

  /**
   * 获取所有已创建的模块名称
   * 
   * @returns 模块名称数组
   */
  static getModules(): string[] {
    return Array.from(this.instances.keys());
  }

  /**
   * 测试日志功能
   * 
   * 创建测试日志，验证配置是否正确
   * 
   * @example
   * ```ts
   * LoggerFactory.test();
   * ```
   */
  static test(): void {
    const logger = this.get('LoggerFactory.test');
    logger.debug('This is a DEBUG message');
    logger.info('This is an INFO message');
    logger.warn('This is a WARN message');
    logger.error('This is an ERROR message');
    
    const authLogger = this.get('LoggerFactory.test', 'auth');
    authLogger.info('Testing auth module logger');
    
    console.log('✅ Logger test completed');
    console.log('📁 Log directory:', this.defaultConfig.logDir);
    console.log('📊 Active modules:', this.getModules());
  }
}

